/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#ifdef OS_CYGWIN
#else
#include "Tracer.h"
#include "FileUtil.h"
#include "HttpRequest.h"
#include "curl/curl.h"
#include <stdlib.h>
#include <string.h>

#define URL_MAX_LEN 2083

namespace libembx{
using namespace libemb;
HttpRequest::HttpRequest()
{
    curl_global_init(CURL_GLOBAL_ALL);
}

HttpRequest::~HttpRequest()
{
    curl_global_cleanup();
}

/**
 *  \brief  发送GET请求
 *  \param  url 目标URL
 *  \param  cacheFile 缓存文件(必须具有可写属性),用于接收服务器回应数据
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR.
 *  \note   none
 */
int HttpRequest::getRequest(const std::string url,File* cacheFile,int timeoutSeconds)
{    
   if (url.size()>URL_MAX_LEN || 
        url.empty() ||
        cacheFile==NULL)
    {
        TRACE_ERR_CLASS("Param Erorr: URL size=%d, cache File=0x%x.\n",url.size(),cacheFile);
        return RC_ERROR;
    }

	FILE* fp = fdopen(cacheFile->fd(),"w");
	if (fp==NULL)
	{
		TRACE_ERR_CLASS("cannot open cache File: %s!\n",ERRSTR);
		return RC_ERROR;
	}
    if (timeoutSeconds<0)
    {
        timeoutSeconds = 20;
    }

    CURL* curl = curl_easy_init();  
    if (curl==NULL)
    {
    	TRACE_ERR_CLASS("curl easy init error!\n");
		return RC_ERROR;
	}
	
    int rc=RC_OK;
    /* 设置URL */
    curl_easy_setopt(curl, CURLOPT_URL, CSTR(url));

    /* 设置返回的数据写入到指定文件 */
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);

    /* 设置请求超时时间 */
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);

    CURLcode res = curl_easy_perform(curl); 
    if(res != CURLE_OK)      
    {
        rc = RC_ERROR;
        TRACE_ERR_CLASS("curl perform: \"%s\"\n",CSTR(url));
		TRACE_ERR_CLASS("curl error  : %s\n",curl_easy_strerror(res));
    }
    curl_easy_cleanup(curl);
    return rc;
}

/**
 *  \brief  发送POST请求
 *  \param  url 目标URL
 *  \param  postString post字符串
 *  \param  cacheFile 缓存文件(必须具有可写属性),用于接收服务器回应数据
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR.
 *  \note   none
 */
int HttpRequest::postRequest(const std::string url,const std::string postString,File* cacheFile,int timeoutSeconds)
{
    if (url.size()>URL_MAX_LEN || 
        url.empty() ||
        cacheFile==NULL)
    {
        TRACE_ERR_CLASS("Param Erorr: URL size=%d, cache File=0x%x.\n",url.size(),cacheFile);
        return RC_ERROR;
    }

	FILE* fp = fdopen(cacheFile->fd(),"w");
	if (fp==NULL)
	{
		TRACE_ERR_CLASS("cannot open cache File: %s!\n",ERRSTR);
		return RC_ERROR;
	}
	
    if (timeoutSeconds<0)
    {
        timeoutSeconds = 20;
    }
    
    CURL* curl = curl_easy_init();  
    if (curl==NULL)
    {
    	TRACE_ERR_CLASS("curl easy init error!\n");
		return RC_ERROR;
	} 
	
    int rc=RC_OK;
    /* 设置URL */
    curl_easy_setopt(curl, CURLOPT_URL, CSTR(url));

    /* 设置返回的数据写入到指定文件 */
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);

    /* 设置请求超时时间 */
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSeconds);

    /* post数据 */
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, CSTR(postString));

    CURLcode res = curl_easy_perform(curl); 
    if(res != CURLE_OK)      
    {
        rc = RC_ERROR;
        TRACE_ERR_CLASS("curl perform: \"%s\"\n",CSTR(url));
		TRACE_ERR_CLASS("curl error  : %s\n",curl_easy_strerror(res));
    }
    curl_easy_cleanup(curl);
    return rc;
}

/**
 *  \brief  文件下载请求
 *  \param  url 目标文件URL
 *  \param  cacheFile 缓存文件(必须具有可写属性),用于接收服务器回应数据
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR.
 *  \note   none
 */
int HttpRequest::fileRequest(const std::string url,File* cacheFile)
{
    if (url.size()>URL_MAX_LEN || 
        url.empty() ||
        cacheFile==NULL)
    {
        TRACE_ERR_CLASS("Param Erorr: URL size=%d, cache File=0x%x.\n",url.size(),cacheFile);
        return RC_ERROR;
    }

	FILE* fp = fdopen(cacheFile->fd(),"wb");
	if (fp==NULL)
	{
		TRACE_ERR_CLASS("cannot open cache File: %s!\n",ERRSTR);
		return RC_ERROR;
	}
    
    CURL* curl = curl_easy_init();  
    if (curl==NULL)
    {
    	TRACE_ERR_CLASS("curl easy init error!\n");
		return RC_ERROR;
	} 
	int rc=RC_OK;
    /* 设置URL */
    curl_easy_setopt(curl, CURLOPT_URL, CSTR(url));

    /* 设置返回的数据写入到指定文件 */
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFuntion);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);

    /* 开始下载 */
    CURLcode res = curl_easy_perform(curl); 
    if(res != CURLE_OK)      
    {
    	rc = RC_ERROR;
        TRACE_ERR_CLASS("curl perform: \"%s\"\n",CSTR(url));
		TRACE_ERR_CLASS("curl error  : %s\n",curl_easy_strerror(res));
    }
    curl_easy_cleanup(curl);
	fclose(fp);
	return rc;
}

int HttpRequest::writeFuntion(void *ptr, int size, int nmemb, FILE *stream) 
{
    int written = fwrite(ptr, size, nmemb, stream);
    return written;
}

}
#endif